package com.atguigu.controller;


import com.atguigu.client.CartFeignClient;
import com.atguigu.client.OrderFeignClient;
import com.atguigu.client.UserFeignClient;
import com.atguigu.constant.MqConst;
import com.atguigu.constant.RedisConst;
import com.atguigu.entity.*;
import com.atguigu.result.RetVal;
import com.atguigu.result.RetValCodeEnum;
import com.atguigu.service.SeckillProductService;
import com.atguigu.util.AuthContextHolder;
import com.atguigu.util.MD5;
import com.atguigu.utils.DateUtil;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author zhufeiyu
 * @since 2022-02-01
 */
@RestController
@RequestMapping("/seckill")
public class SeckillController {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillProductService seckillService;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private UserFeignClient userFeignClient;
    @Autowired
    private OrderFeignClient orderFeignClient;

    //1.查询秒杀商品列表
    @GetMapping("queryAllSeckillProduct")
    public RetVal queryAllSeckillProduct() {
        List<SeckillProduct> seckillProductList = redisTemplate.boundHashOps(RedisConst.SECKILL_PRODUCT).values();
        return RetVal.ok(seckillProductList);
    }

    //2.查询秒杀商品详情信息
    @GetMapping("querySeckillProductById/{skuId}")
    public RetVal querySeckillProductById(@PathVariable Long skuId) {
        SeckillProduct seckillProduct = seckillService.querySeckillProductById(skuId);
        return RetVal.ok(seckillProduct);
    }

    //3.生成抢购码 防止用户直接跳过商品详情页面进入秒杀地址 seckill/generateSeckillCode/24
    @GetMapping("generateSeckillCode/{skuId}")
    public RetVal generateSeckillCode(@PathVariable Long skuId, HttpServletRequest request) {
        //a.判断用户是否登录
        String userId = AuthContextHolder.getUserId(request);
        if (!StringUtils.isEmpty(userId)) {
            //b.从缓存中拿到秒杀商品
            SeckillProduct seckillProduct = seckillService.querySeckillProductById(skuId);
            //c.判断当前时间是否在秒杀范围之内 生成抢购码
            Date nowTime = new Date();
            if (DateUtil.dateCompare(seckillProduct.getStartTime(), nowTime) &&
                    DateUtil.dateCompare(nowTime, seckillProduct.getEndTime())) {
                //d.利用MD5对userId加密
                String secKillCode = MD5.encrypt(userId);
                return RetVal.ok(secKillCode);
            }
        }
        return RetVal.fail().message("获取抢购码失败,请登录");
    }

    //4.秒杀预下单--预售
    @PostMapping("prepareSeckill/{skuId}")
    public RetVal prepareSeckill(@PathVariable Long skuId, String seckillCode, HttpServletRequest request) {
        //a.判断抢购码是否正确
        String userId = AuthContextHolder.getUserId(request);
        if (!MD5.encrypt(userId).equals(seckillCode)) {
            //抢购码不合法 报异常
            return RetVal.build(null, RetValCodeEnum.SECKILL_ILLEGAL);
        }
        //b.秒杀商品是否可以进行秒杀 状态是否为1 seckill:state:24
        String state = (String) redisTemplate.opsForValue().get(RedisConst.SECKILL_STATE_PREFIX + skuId);
        if (StringUtils.isEmpty(state)) {
            return RetVal.build(null, RetValCodeEnum.SECKILL_ILLEGAL);
        }
        //可以进行秒杀
        if (RedisConst.CAN_SECKILL.equals(state)) {
            //c.如果可以进行秒杀 生成一个预订单 发送消息给rabbitmq
            UserSeckillSkuInfo userSeckillSkuInfo = new UserSeckillSkuInfo();
            userSeckillSkuInfo.setUserId(userId);
            userSeckillSkuInfo.setSkuId(skuId);
            rabbitTemplate.convertAndSend(MqConst.PREPARE_SECKILL_EXCHANGE, MqConst.PREPARE_SECKILL_ROUTE_KEY, userSeckillSkuInfo);
        } else {
            //秒杀商品已售罄
            return RetVal.build(null, RetValCodeEnum.SECKILL_FINISH);
        }
        return RetVal.ok();
    }

    //5.查询用户是否有抢购资格 hasQualified
    @GetMapping("hasQualified/{skuId}")
    public RetVal hasQualified(@PathVariable Long skuId, HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);
        return seckillService.hasQualified(skuId, userId);
    }

    //6.查询用户是否有抢购资格 hasQualified
    @GetMapping("seckillConfirm")
    public RetVal seckillConfirm(HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);
        //a.地址信息(shop-user)
        List<UserAddress> userAddressList = userFeignClient.getUserAddressByUserId(userId);
        //b.送货清单--从redis中拿到预购订单
        PrepareSeckillOrder prepareSeckillOrder = (PrepareSeckillOrder) redisTemplate.boundHashOps(RedisConst.PREPARE_SECKILL_USERID_ORDER).get(userId);
        if (prepareSeckillOrder == null) {
            return RetVal.fail().message("非法请求");
        }
        //c.把预购订单中的商品改造为商品详情
        SeckillProduct seckillProduct = prepareSeckillOrder.getSeckillProduct();
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setSkuId(seckillProduct.getSkuId());
        orderDetail.setSkuName(seckillProduct.getSkuName());
        orderDetail.setImgUrl(seckillProduct.getSkuDefaultImg());
        orderDetail.setOrderPrice(seckillProduct.getCostPrice());
        orderDetail.setSkuNum(prepareSeckillOrder.getBuyNum() + "");

        List<OrderDetail> detailArrayList = new ArrayList<>();
        detailArrayList.add(orderDetail);

        Map<String, Object> retMap = new HashMap<>();
        //地址信息
        retMap.put("userAddressList", userAddressList);
        //送货清单
        retMap.put("orderDetailList", detailArrayList);
        //订单总金额
        retMap.put("totalMoney", seckillProduct.getCostPrice());

        return RetVal.ok(retMap);
    }

    //7.提交秒杀订单信息 http://api.gmall.com/seckill/submitSecKillOrder
    @PostMapping("submitSecKillOrder")
    public RetVal submitSecKillOrder(@RequestBody OrderInfo orderInfo, HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);
        //a.判断用户是否有预购订单
        PrepareSeckillOrder prepareSeckillOrder = (PrepareSeckillOrder) redisTemplate.boundHashOps(RedisConst.PREPARE_SECKILL_USERID_ORDER).get(userId);
        if (prepareSeckillOrder == null) {
            return RetVal.fail().message("非法请求");
        }
        //b.通过远程order微服务调用下订单接口
        Long orderId = orderFeignClient.saveOrderAndDetail(orderInfo);
        if (orderId == null) {
            return RetVal.fail().message("下单失败");
        }
        //c.删除redis里面的预订单信息
        redisTemplate.boundHashOps(RedisConst.PREPARE_SECKILL_USERID_ORDER).delete(userId);
        //d.在redis中把用户购买的商品信息放到redis中 用于判断用户是否购买过
        redisTemplate.boundHashOps(RedisConst.BOUGHT_SECKILL_USER_ORDER).put(userId, orderId);
        return RetVal.ok(orderId);
    }
}

